use super::DataAccessTrait;
use super::{Error, Result};
use static_init::dynamic;
use std::collections::HashMap;
use std::sync::{Arc, RwLock};

struct DaoMap(Arc<RwLock<HashMap<String, Box<&'static dyn DataAccessTrait>>>>);

impl DaoMap {
    fn new() -> Self {
        let dao_map: HashMap<String, Box<&'static dyn DataAccessTrait>> = HashMap::new();
        DaoMap(Arc::new(RwLock::new(dao_map)))
    }
    fn get(&self, dao_name: &str) -> Result<&dyn DataAccessTrait> {
        let dm = self.0.read().unwrap();
        let dao_opt = dm.get(dao_name);
        if let Some(dao) = dao_opt {
            let dao_ref = dao.as_ref();
            Ok(*dao_ref)
        } else {
            Err(Error::from(format!("dao_name:{}没有找到", dao_name)))
        }
    }
}

#[dynamic]
static DAO_MAP: DaoMap = DaoMap::new();

pub fn get_dao(dao_name: &str) -> Result<&'static dyn DataAccessTrait> {
    let dao = DAO_MAP.get(dao_name)?;
    Ok(dao)
}

pub fn set_dao(dao_name:&str, dao: &'static impl DataAccessTrait) {
    let mut dm = DAO_MAP.0.write().unwrap();
    let name=dao_name.to_lowercase();
    dm.insert(name, Box::new(dao));
}
